/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.util.UUID;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.enumerated.LetterCase;
import org.zhiqim.kernel.model.seqs.Sequence;

/**
 * ID编号相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 * @version v1.4.0 @author zouzhigang 2018-1-1  增加long13方法支持条型码
 * @version v1.4.1 @author zouzhigang 2018-4-20 修改UUID默认为小写，增加指定大小写参数
 * @version v1.5.2 @author zouzhigang 2019-5-31 增加toDateTime方法转为时间格式
 */
@AnAlias("Ids")
public class Ids implements SignConstants
{
    private static final Sequence sequence3 = new Sequence(3);
    private static final Sequence sequence4 = new Sequence(4);
    private static final Sequence sequence5 = new Sequence(5);
    private static final Sequence sequence8 = new Sequence(8);
    
    /***************************************************************************************************/
    //32位通用唯一识别码字符串（Universally Unique Identifier）
    /***************************************************************************************************/
    
    /** 32位通用唯一识别码 */
    public static final String uuid()
    {
        return UUID.randomUUID().toString().replaceAll("-", _EMPTY_);
    }
    
    /** 32位通用唯一识别码，指定大小写 */
    public static final String uuid(LetterCase letter)
    {
        return letter.toCase(uuid(), LetterCase.LOWER);
    }
    
    /***************************************************************************************************/
    //16位唯一长整数，由12位秒级+4位序列号,JS支持最大值16位（9007199254740992），所以16位在JSON中比较合适
    /***************************************************************************************************/
    
    /** 16位唯一长整数 */
    public static final long longId()
    {
        return longId(sequence4);
    }
    
    /** 16位唯一长整数，指定长度为4位数的序列对象 */
    public static final long longId(Sequence sequence4)
    {
        long time = Longs.toLong(DateTimes.getDateTime12String());
        long seq = sequence4.next();
        
        return time * 10000L + seq;
    }
    
    /** 16位唯一长整数，转为时间字符串 */
    public static final String toDateTime(long id)
    {
        String time = String.valueOf(id / 10000);
        return new StringBuilder("20").append(time.substring(0, 2)).append("-")
                                       .append(time.substring(2, 4)).append("-")
                                       .append(time.substring(4, 6)).append(" ")
                                       .append(time.substring(6, 8)).append(":")
                                       .append(time.substring(8, 10)).append(":")
                                       .append(time.substring(10))
                                       .toString();
    }
    
    /***************************************************************************************************/
    //18位唯一长整数，由10位秒级+8位序列号,1秒1亿内，基本上不用担心中小项目会重复
    /***************************************************************************************************/
    
    /** 13位唯一长整数 */
    public static final long longId18()
    {
        return longId18(sequence8);
    }
    
    /** 13位唯一长整数，指定长度为3位数的序列对象 */
    public static final long longId18(Sequence sequence8)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long currtime = System.currentTimeMillis() / 1000;
        
        long seq = sequence8.next();
        return (year % 100) * 10000000000000000L + (currtime - yearTime) * 100000000 + seq;
    }
    
    /** 13位唯一长整数，转为时间字符串 */
    public static final String toDateTime18(long id)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long datetime = yearTime + id / 100000000 % 100000000L;
        
        return DateTimes.toDateTimeString(datetime * 1000);
    }
    
    /***************************************************************************************************/
    //13位唯一长整数，由2位年数+当年8位秒数+3位序列号，支持条形码，有效至2099年
    /***************************************************************************************************/
    
    /** 13位唯一长整数 */
    public static final long longId13()
    {
        return longId13(sequence3);
    }
    
    /** 13位唯一长整数，指定长度为3位数的序列对象 */
    public static final long longId13(Sequence sequence3)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long currtime = System.currentTimeMillis() / 1000;
        
        long seq = sequence3.next();
        return (year % 100) * 100000000000L + (currtime - yearTime) * 1000 + seq;
    }
    
    /** 13位唯一长整数，转为时间字符串 */
    public static final String toDateTime13(long id)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long datetime = yearTime + id / 1000 % 100000000L;
        
        return DateTimes.toDateTimeString(datetime * 1000);
    }
    
    /** 13位唯一长整数 */
    public static final long longId13_4()
    {
        return longId13_4(sequence4);
    }
    
    /** 13位唯一长整数，指定长度为4位数的序列对象，对一年时间/3.16224 */
    public static final long longId13_4(Sequence sequence4)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long currtime = System.currentTimeMillis() / 1000;
        
        long seq = sequence4.next();
        return (year % 100) * 100000000000L + (long)((currtime - yearTime) / 3.16224) * 10000 + seq;
    }
    
    /** 13位唯一长整数，指定长度为4位数的序列对象，对一年时间/3.16224，转为时间字符串 */
    public static final String toDateTime13_4(long id)
    {
        int year = DateTimes.getCurrentYear();
        long yearTime = DateTimes.toLong(year, 1, 1, 0, 0, 0) / 1000;
        long datetime = (long)(id / 10000 % 10000000L * 3.16224) + yearTime;
        
        return DateTimes.toDateTimeString(datetime * 1000);
    }
    
    /**********************************************************************************************/
    //19位唯一长整数，由14位秒级+5位序列号，有效至9223年，long型最大值为19位（9223372036854775807）
    /**********************************************************************************************/
    
    /** 19位唯一长整数 */
    public static final long longId19()
    {
        return longId19(sequence5);
    }
    
    /** 19位唯一长整数，指定长度为5位数的序列对象 */
    public static final long longId19(Sequence sequence5)
    {
        long time = Longs.toLong(DateTimes.getDateTime14String());
        long seq = sequence5.next();
        
        return time * 100000L + seq;
    }
    
    /** 19位唯一长整数，转为时间字符串 */
    public static final String toDateTime19(long id)
    {
        String time = String.valueOf(id / 100000);
        return new StringBuilder(time.substring(0, 4)).append("-")
                          .append(time.substring(4, 6)).append("-")
                          .append(time.substring(6, 8)).append(" ")
                          .append(time.substring(8, 10)).append(":")
                          .append(time.substring(10, 12)).append(":")
                          .append(time.substring(12))
                          .toString();
    }
}
